package jwt

import (
	"crypto/rsa"
	"errors"

	"qingbing/xzutils/files"

	"github.com/golang-jwt/jwt"
)

// 使用 rsa 的 jwt 封装
type Rsa struct {
	PublicKey  *rsa.PublicKey
	PrivateKey *rsa.PrivateKey
}

// jwt-rsa 加密数据
func (j *Rsa) GenerateToken(claims jwt.Claims) (token string, err error) {
	return jwt.
		NewWithClaims(jwt.SigningMethodRS256, claims).
		SignedString(j.PrivateKey) // key 要和 NewWithClaims 的 method 对应
}

// jwt-rsa 解密 token
func (j *Rsa) ParseToken(tokenString string, claim jwt.Claims) error {
	pToken, err := jwt.ParseWithClaims(tokenString, claim, func(token *jwt.Token) (interface{}, error) {
		return j.PublicKey, nil
	})
	if err != nil {
		return err
	}
	return pToken.Claims.Valid()
}

/**
 * Rsa非对称加密形式的 jwt 配置数据结构
 */
type ConfRsa struct {
	PubKeyFile string // 公钥文件路径
	PriKeyFile string // 私钥文件路径
	Password   string // 密码
}

// 新建 jwt-rsa 组件
func NewRsa(conf *ConfRsa) (jt IJwtEntry, err error) {
	priKeyBs, err := files.ReadFile(conf.PriKeyFile)
	if err != nil {
		err = errors.New("读取私钥失败")
		return
	}
	rsaPriKey, err := jwt.ParseRSAPrivateKeyFromPEMWithPassword(priKeyBs, conf.Password)
	if err != nil {
		err = errors.New("解析私钥失败")
		return
	}

	pubKeyBs, err := files.ReadFile(conf.PubKeyFile)
	if err != nil {
		err = errors.New("读取公钥失败")
		return
	}
	rsaPubKey, err := jwt.ParseRSAPublicKeyFromPEM(pubKeyBs)
	if err != nil {
		err = errors.New("解析私钥失败")
		return
	}
	jt = &Rsa{
		PublicKey:  rsaPubKey,
		PrivateKey: rsaPriKey,
	}
	return
}
